﻿//-----------------------------------------------------------------------
// <copyright file="ItemTaggerThread.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
// </copyright>
// <author>Yogesh M Joshi</author>
// <email>ymjoshi@live.com</email>
// <date>16-May-2011</date>
//-----------------------------------------------------------------------

namespace SmartTag.Application.Tagging
{
    using System;
    using System.Collections.Generic;
    using System.Threading;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Taxonomy;
    using SmartTag.Application.CommandLine;

    /// <summary>
    /// This class represents item tagger worker thread
    /// </summary>
    internal class ItemTaggerThread
    {
        #region "Private Fields"

        /// <summary>
        /// Queue of the list items
        /// </summary>
        private Queue<SPListItem> itemQueue;

        /// <summary>
        /// Synchronization object
        /// </summary>
        private object lockObject;

        /// <summary>
        /// Operation completed event
        /// </summary>
        private ManualResetEvent doneEvent;

        /// <summary>
        /// Flag to represent if we need to stop the operation
        /// </summary>
        private bool shallStop = false;

        /// <summary>
        /// Terms are pre-fetched per column basis in termsRepository
        /// </summary>
        private Dictionary<string, List<Term>> termsRepository = new Dictionary<string, List<Term>>();

        /// <summary>
        /// Fields are pre-identified before we start worker threads
        /// </summary>
        private Dictionary<string, SPField> fieldRepository = new Dictionary<string, SPField>();

        /// <summary>
        /// Number of words to scan in given document
        /// P.S. This is an approximate count
        /// </summary>
        private int wordsToScan;

        /// <summary>
        /// Relevance of the term
        /// </summary>
        private int relevance;

        #endregion

        /// <summary>
        /// Initializes a new instance of the ItemTaggerThread class
        /// </summary>
        /// <param name="itemQueue">Queue of the list items</param>
        /// <param name="fieldRepository">Fields to tag</param>
        /// <param name="termsRepository">Terms to be used</param>
        /// <param name="wordsToScan">Number of words to be scanned from document</param>
        /// <param name="relevance">Relevance of the term</param>
        /// <param name="lockObject">Synchronization object</param>
        /// <param name="doneEvent">Operation completed event</param>
        public ItemTaggerThread(
            Queue<SPListItem> itemQueue,
            Dictionary<string, SPField> fieldRepository,
            Dictionary<string, List<Term>> termsRepository,
            int wordsToScan,
            int relevance,
            object lockObject,
            ManualResetEvent doneEvent)
        {
            this.itemQueue = itemQueue;
            this.fieldRepository = fieldRepository;
            this.termsRepository = termsRepository;
            this.wordsToScan = wordsToScan;
            this.relevance = relevance;
            this.lockObject = lockObject;
            this.doneEvent = doneEvent;
        }

        /// <summary>
        /// Stops the current thread
        /// </summary>
        public void Stop()
        {
            this.shallStop = true;
        }

        /// <summary>
        /// Worker thread proc
        /// </summary>
        /// <param name="threadContext">Current thread context</param>
        public void TaggerThreadFunc(object threadContext)
        {
            SPListItem item = null;
            
            Logger.LogMessage("Starting item tagging thread...");

            while (this.shallStop == false)
            {
                lock (this.lockObject)
                {
                    if (this.itemQueue.Count == 0 && this.shallStop != true)
                    {
                        Monitor.PulseAll(this.lockObject);
                        Monitor.Wait(this.lockObject);
                        continue;
                    }

                    if (this.shallStop == true)
                    {
                        break;
                    }

                    item = this.itemQueue.Dequeue();
                }

                if (item != null)
                {
                    Logger.LogMessage("Tagged : " + item.File.Name);
                    ItemTagger tagger = new ItemTagger(item, this.fieldRepository, this.termsRepository, this.wordsToScan, this.relevance);
                    tagger.Tag();
                }
            }

            // Tell that we are done
            this.doneEvent.Set();

            Logger.LogMessage("Exiting item tagging thread...");
        }
    }
}
